/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nus.application.ejb.user.impl;

import com.nus.application.ejb.user.ConferenceEjbLocal;
import com.nus.constant.ConstantStatus;
import com.nus.dataaccess.dao.conference.Conference;
import com.nus.dataaccess.dao.conference.ConferenceAuthor;
import com.nus.dataaccess.dao.conference.dao.ConferenceAuthorDao;
import com.nus.dataaccess.dao.conference.dao.ConferenceDao;
import com.nus.dataaccess.dao.review.ReviewAssignment;
import com.nus.dataaccess.dao.review.dao.ReviewAssignmentDao;
import com.nus.dataaccess.dao.user.dao.UserInfoDao;
import com.nus.dataaccess.dao.util.HibernateUtil;
import com.nus.util.BeanUtil;
import com.nus.util.comparator.ConferenceAuthorScoreComparator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.security.PermitAll;
import javax.ejb.Stateless;

/**
 *
 * @author robin.foe
 */
@Stateless
@PermitAll
public class ConferenceEjb implements ConferenceEjbLocal {

    @Override
    public String getTestString() {
        return "Hello this is my first EJB";
    }

    @Override
    public List<Conference> listAllConference() {
        return ConferenceDao.getInstance().findAll();
    }

    @Override
    public Conference retrieveConferenceById(Long id) {
        return ConferenceDao.getInstance().getConferenceById(id);
    }

    @Override
    public void persistConference(Conference conference) {
        try {
            HibernateUtil.beginTransaction();
            ConferenceDao.getInstance().saveOrUpdate(conference);
            HibernateUtil.commitTransaction();
        } catch (Exception e) {
            HibernateUtil.rollbackTransaction();
        }
    }

    @Override
    public void publishConferenceItem(Long conferenceId){
        try {
            HibernateUtil.beginTransaction();
            Conference conference = ConferenceDao.getInstance().get(conferenceId);

            List<ConferenceAuthor> conferenceAuthors = conference.getConferenceAuthors();
            for(ConferenceAuthor conferenceAuthor : conferenceAuthors){
                conferenceAuthor.populateAverageScore();
            }

            Collections.sort(conferenceAuthors, new ConferenceAuthorScoreComparator());
            BigDecimal totalSize = new BigDecimal(conferenceAuthors.size());

            // we need to pick only top 30%
            totalSize = totalSize.divide(new BigDecimal(30),2, RoundingMode.UP);
            totalSize.multiply(new BigDecimal(100));
            int publishedCount = totalSize.intValue();
            for(int i = 0; i < conferenceAuthors.size(); i++){
                ConferenceAuthor conferenceAuthor = conferenceAuthors.get(i);
                conferenceAuthor.setPublishStatus((i<=publishedCount ) ? ConstantStatus.CONF_STS_PUBLISHED : ConstantStatus.CONF_STS_REJECTED);
                ConferenceAuthorDao.getInstance().saveOrUpdate(conferenceAuthor);
            }
            HibernateUtil.commitTransaction();
        } catch (Exception e) {
            HibernateUtil.rollbackTransaction();
        }


    }

    @Override
    public List<Conference> paginateConference(int first, int pageSize, String sortField, boolean ascending, Map<String, Object> filters) {
        return ConferenceDao.getInstance().paginate(first, pageSize, sortField, ascending, filters);
    }

    @Override
    public int countPaginateConference(Map<String, Object> filters) {
        return ConferenceDao.getInstance().getTotalCount(filters);
    }

    @Override
    public void deleteConference(Conference conference) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /***********************AUTHOR RELATED***********************/
    @Override
    public List<ConferenceAuthor> paginateConferenceAuthor(int first, int pageSize, String sortField, boolean ascending, Map<String, Object> filters){
        return ConferenceAuthorDao.getInstance().paginate(first, pageSize, sortField, ascending, filters);
    }

    @Override
    public int getTotalCountConferenceAuthor(Map<String, Object> filters){
        return ConferenceAuthorDao.getInstance().getTotalCount(filters);
    }

    @Override
    public List<ConferenceAuthor> paginateConferenceAuthorByAuthor(Long authorId, int first, int pageSize, String sortField, boolean ascending, Map<String, Object> filters){
        return ConferenceAuthorDao.getInstance().paginateByAuthorId(authorId, first, pageSize, sortField, ascending, filters);
    }

    @Override
    public int getTotalCountConferenceAuthorByAuthor(Long authorId , Map<String, Object> filters){
        return ConferenceAuthorDao.getInstance().getTotalCountByAuthorId(authorId, filters);
    }



    @Override
    public ConferenceAuthor retrieveConferenceAuthor(Long conferencAuthorId){
        ConferenceAuthor conferenceAuthor = ConferenceAuthorDao.getInstance().get(conferencAuthorId);
        conferenceAuthor.setReviewer(null);
        ConferenceAuthorDao.getInstance().refresh(conferenceAuthor);
        return conferenceAuthor;
    }

    @Override
    public void persistReviewAssignment(ConferenceAuthor conferenceAuthor){

        try{
            HibernateUtil.beginTransaction();

            List<ReviewAssignment> reviewAssignments = conferenceAuthor.getReviewer();
            ConferenceAuthor conferenceAuthorDb = this.retrieveConferenceAuthor(conferenceAuthor.getId());

            List<ReviewAssignment> deleteList = new ArrayList<ReviewAssignment>();
            for(ReviewAssignment dbReviewAssignment : conferenceAuthorDb.getReviewer() ){
                    if(!reviewAssignments.contains(dbReviewAssignment))
                        deleteList.add(dbReviewAssignment);
            }

            for(ReviewAssignment deleteReview : deleteList){
                conferenceAuthorDb.getAuthors().remove(deleteReview);
                ReviewAssignmentDao.getInstance().delete(ReviewAssignmentDao.getInstance().get(deleteReview.getId()));
            }

            for(ReviewAssignment reviewAssignment : reviewAssignments){
                if(!reviewAssignment.isPkSet())
                    ReviewAssignmentDao.getInstance().saveOrUpdate(reviewAssignment);
                else{
                    ReviewAssignment dbReviewAssignment = ReviewAssignmentDao.getInstance().get(reviewAssignment.getId());
                    BeanUtil.copyProperties(dbReviewAssignment, reviewAssignment, "id", "reviewStatus","conferenceAuthor","reviewer");
                    ReviewAssignmentDao.getInstance().saveOrUpdate(dbReviewAssignment);
                }
            }
            HibernateUtil.commitTransaction();
        }catch(Exception e){
            HibernateUtil.rollbackTransaction();
            e.printStackTrace();
        }finally{

            try{
                HibernateUtil.closeSession();
            }catch(Exception e){
            e.printStackTrace();
            }
        }

    }

}
